package com.hy.server;

import com.hy.core.ChannelContext;
import com.hy.core.ReadCompletionHandler;

import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * author: houying
 * date  : 17-6-8
 * desc  :
 */
public class ServerChannelContext implements ChannelContext, Closeable {

    public final int CORE_SIZE = Runtime.getRuntime().availableProcessors() * 2;
    private final ReadCompletionHandler readCompletionHandler;
    private final AcceptCompletionHandler acceptCompletionHandler;
    private final ServerActionListener listener;
    private final ServerHandler handler;

    private ThreadPoolExecutor pool;
    private AsynchronousChannelGroup channelGroup;
    private AsynchronousServerSocketChannel serverSocketChannel;

    public ServerChannelContext(ServerActionListener listener, ServerHandler serverHandler) throws IOException {
        pool = new ThreadPoolExecutor(CORE_SIZE, CORE_SIZE * 2, 10, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(CORE_SIZE * 2));
        pool.prestartCoreThread();

        channelGroup = AsynchronousChannelGroup.withThreadPool(pool);
        serverSocketChannel = AsynchronousServerSocketChannel.open(channelGroup);

        this.listener = listener;
        this.handler = serverHandler;

        readCompletionHandler = new ReadCompletionHandler(handler);
        acceptCompletionHandler = new AcceptCompletionHandler();
    }

    public AsynchronousServerSocketChannel getServerSocketChannel() {
        return serverSocketChannel;
    }

    public ReadCompletionHandler getReadCompletionHandler() {
        return readCompletionHandler;
    }

    public AcceptCompletionHandler getAcceptCompletionHandler() {
        return acceptCompletionHandler;
    }

    @Override
    public void close() throws IOException {
        if (!pool.isShutdown()) {
            pool.shutdown();
        }
        try {
            if (!pool.awaitTermination(5, TimeUnit.SECONDS)) {
                pool.shutdownNow();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        channelGroup.shutdownNow();
        serverSocketChannel.close();
    }
}
